home *** CD-ROM | disk | FTP | other *** search
/ BBS Toolkit / BBS Toolkit.iso / rbbs_pc / othello.zip / OTHELLO.C next >
C/C++ Source or Header  |  1986-05-23  |  11KB  |  549 lines

  1. /*
  2. OTHELLO -- The Game of Dramatic Reversals
  3.  
  4.     written by Bert Halstead
  5.     modified for BDS C by Leor Zolman
  6.     converted for MS-DOS by Chuck Hoelzen
  7.  
  8.    Object of the game is for two players to alternate
  9. placing their marker someplace on an 8 by 8 grid, so that
  10. at least one of the opponent's pieces becomes surrounded
  11. by the moving player's peices -- causing the flanked pieces
  12. to flip 'color' and belong to the moving player. After 60
  13. moves have been played (or if no player has a legal move left),
  14. the player with the most of his own pieces on the board wins.
  15.  
  16.    The playing pieces are '*' and '@'. You may choose to play
  17. either '*' or '@' for the first game; thereafter, you and the
  18. computer will alternate going first for each game. Whoever
  19. goes first always plays `*'.
  20.  
  21.    You enter a move as a two digit number, each digit being
  22. from 1 to 8, first digit representing row and second representing
  23. column. For example: if playing '*', your first move might be '46',
  24. meaning 4th row down, 6th position across.
  25.  
  26.    As an alternative to entering a move, one of the following
  27. commands may be typed:
  28.  
  29.     g    causes computer to play both sides until game
  30.         is over
  31.  
  32.     a    causes computer to print out an analysis of
  33.         each of your possible moves. A letter from A
  34.         to Z will appear at each of your legal move
  35.         positions, where A is the machine's opinion
  36.         of an excellant move and Z is a real loser.
  37.  
  38.     hn    sets handicap. n is 1,2,3, or 4. If n is
  39.         positive, gives n free pieces to the computer.
  40.         If n is negative, gives YOU the free peices.
  41.  
  42.     f    forfeit the current move. This happens
  43.         automatically if you have no legal moves.
  44.  
  45.     q    quit the current game.
  46.  
  47.     b    prints out board again.
  48.  
  49.     s    prints out the score, and tells who is winning.
  50. */
  51.  
  52. #include "stdio.h"
  53. #define BLACK '*'
  54. #define WHITE '@'
  55. #define EMPTY '-'
  56.  
  57.  
  58. int handicap;
  59. char selfplay;        /* true if computer playing with itself */
  60. int h[4][2];        /* handicap position table */
  61. char mine, his;        /* who has black (*) and white (@) in current game */
  62. char mefirst;        /* true if computer goes first in current game */
  63.  
  64. char skipbl()
  65. {
  66.     char c;
  67.     while ((c = toupper(getchar())) == ' ' || c=='\t');
  68.     return c;
  69. }
  70.  
  71.  
  72. char ask(s)
  73. char *s;
  74. {
  75.     char a,c;
  76.     printf ("%s ",s);
  77.     a=skipbl();
  78.     while (c != 0xd && c != 4) c= getchar();
  79.     return a;
  80. }
  81.  
  82. main(argc,argv)
  83. int argc;
  84. char **argv;
  85. {
  86.     char b[8][8];
  87.     int i;
  88.     h[0][0] = h[0][1] = h[2][0] = h[3][1] = 0;
  89.     h[1][0] = h[1][1] = h[2][1] = h[3][0] = 7;
  90.     printf("\nWelcome to the OTHELLO program!\n");
  91.     printhelp();
  92.     printf("\nNote: `*' always goes first...Good luck!!!\n\n");
  93.  
  94.     printf("Do you want to go first? ");
  95.     if (toupper(getchar()) == 'Y') 
  96.         mefirst = 0;
  97.     else
  98.         mefirst = 1;
  99.  
  100.     printf("\n\n");
  101.  
  102.     do {
  103.         clrbrd(b);
  104.         prtbrd(b);
  105.         i = game(b,4);
  106.         mefirst = !mefirst;
  107.         if (i==4) break;
  108.         if (i=='Q') continue;
  109.         printf("\n");
  110.         i = prtscr(b);
  111.         if (i>0) printf(" You won by %d\n",i);
  112.         else if (i<0) printf(" You lost by %d\n",-i);
  113.         else printf(" A draw\n");
  114.     } while (ask("Another game? ")=='Y');
  115. }
  116.  
  117. char getmov(i,j)
  118. int *i, *j;
  119. {
  120.     char a,c;
  121.     int n;
  122.     char *p;
  123.     char skipbl();
  124.     if (selfplay == 'G') {
  125.         if (!csts()) return 'G';
  126.         selfplay = ' ';
  127.         getchar();
  128.     }
  129.     printf("Move: ");
  130.     while(1) switch (c=skipbl()) {
  131.         case 0xd: printf("Move?  "); continue;
  132.         case 'G': if ((c = skipbl()) != 0xd)
  133.                 goto flush;
  134.             selfplay='G';
  135.             return 'G';
  136.         case 'B': case 'S': case 'Q':
  137.         case 'F': case 'A':
  138.           a=c;
  139.           if (( c = skipbl()) != 0xd) goto flush;
  140.           return a;
  141.         case 'H': if ((a=c=skipbl()) == EMPTY)
  142.                 c=getchar();
  143.             if (c<'1' || c>'4' || skipbl() !=0xd)
  144.                 goto flush;
  145.             *i = a==EMPTY? -(c-'0') : (c-'0');
  146.             return 'H';
  147.         case 4: return c;
  148.         default: if (c<'1' || c>'8') goto flush;
  149.             *i = c-'1';
  150.             c = skipbl();
  151.             if (c<'1' || c>'8') goto flush;
  152.             *j = c- '1';
  153.             if ((c=skipbl()) == 0xd) return 'M';
  154.         flush:    while (c != 0xd && c != 4)
  155.                 c=getchar();
  156.             if (c==4) return c;
  157.             printf ("Huh?? ");
  158.             printf("\nCommands are:(A) (B)oard (F)orfit (G)o (H)ard (Q)uit (S)core (88) move row-col\n");
  159.         }
  160. }
  161.  
  162. game(b,n)
  163. char b[8][8];
  164. int n;
  165. {
  166.     char c;
  167.     int ff;
  168.     int i,j;
  169.     handicap = 0;
  170.     selfplay = ' ';
  171.     ff=0;
  172.  
  173.     if (mefirst) {
  174.         mine = BLACK; his = WHITE;
  175.         printf("\nI go first:\n\n");
  176.     }
  177.     else {
  178.         mine = WHITE; his = BLACK;
  179.         printf("\nYou go first:\n\n");
  180.     }
  181.  
  182.     while(1) {
  183.         if (cntbrd(b,EMPTY)==0) return 'D';
  184.         if (cntbrd(b,EMPTY)==60 && mine == BLACK) goto Istart;
  185.         if (chkmvs(b,his)==0) {
  186.             printf(!mefirst ? "Forfeit" : "   ...Forfeit\n");
  187.             ff |= 1;
  188.             }
  189.         else switch (c = getmov(&i,&j)) {
  190.         case 'B': prtbrd(b); continue;
  191.         case 'S': i= prtscr(b);
  192.             if (i>0) printf(" You're winning\n");
  193.             else if (i<0)printf(" You're losing!\n");
  194.             else putchar('\n');
  195.             continue;
  196.         case 'Q': case 4: return c;
  197.  
  198.         case 'H': if (n>abs(handicap)+4)
  199.                 printf("Illegal!\n");
  200.             else for (j=0; i!=0; j++) {
  201.              b[h[j][0]][h[j][1]]= i>0?BLACK:WHITE;
  202.              handicap += i>0 ? 1 : -1;
  203.              ++n;
  204.              i += i>0 ? -1 : 1;
  205.             }
  206.             prtbrd(b); continue;
  207.         case 'A': analyze(b,his,mine,EMPTY);
  208.             continue;
  209.         case 'G': my_mov(b,his,mine,EMPTY,&i,&j);
  210.         case 'M': if (chkmov(b,his,i,j)>0) {
  211.             printf(!mefirst ? "%1d-%1d" : "   ...%1d-%1d\n",
  212.                 i+1,j+1);
  213.             putmov(b,his,i,j);
  214.             }
  215.             else {
  216.               printf("Illegal!\n");
  217.               continue;
  218.              }
  219.             break;
  220.         case 'F': if (n>abs(handicap)+4) {
  221.             printf ("Illegal!\n");
  222.             continue;
  223.              }
  224.             else printf(!mefirst ? "Forfeit" :
  225.                          "   ...Forfeit\n");
  226.         }
  227. Istart:        if (cntbrd(b,EMPTY) == 0) return 'D';
  228.         if (chkmvs(b,mine)==0) {
  229.             printf(!mefirst ? "...Forfeit\n": "Forfeit...\n");
  230.             ff |=2;
  231.             }
  232.         else {
  233.             my_mov(b,mine,his,EMPTY,&i,&j);
  234.             printf(!mefirst ? "...%1d-%1d\n" : "%1d-%1d...\n",
  235.                 i+1,j+1);
  236.             putmov(b,mine,i,j);
  237.             ++n;
  238.             }
  239.         if (ff==3 || n>64) return 'D';
  240.         if (!(ff & 1)) prtbrd(b);
  241.         ff = 0;
  242.     }
  243. }
  244.  
  245.  
  246. prtscr(b)
  247. char *b;
  248. {
  249.     int i,j;
  250.     printf("%1d-%1d",i = cntbrd(b,his), j=cntbrd(b,mine));
  251.     return i-j;
  252. }
  253.  
  254.  
  255.  
  256. chkmvs(b,p)
  257. char b[8][8];
  258. char p;
  259. {
  260.     int i,j,k;
  261.     k=0;
  262.     for (i=0; i<8; i++) for (j=0; j<8; j++)
  263.         k += chkmov(b,p,i,j);
  264.     return k;
  265. }
  266.  
  267.  
  268. chkmov(b,p,x,y)
  269. char b[8][8],p;
  270. int x,y;
  271. {
  272.     if (b[x][y] != EMPTY) return 0;
  273.     return    chkmv1(b,p,x,y,0,1) + chkmv1(b,p,x,y,1,0) +
  274.         chkmv1(b,p,x,y,0,-1)+ chkmv1(b,p,x,y,-1,0)+
  275.         chkmv1(b,p,x,y,1,1) + chkmv1(b,p,x,y,1,-1)+
  276.         chkmv1(b,p,x,y,-1,1)+ chkmv1(b,p,x,y,-1,-1);
  277. }
  278.  
  279.  
  280. chkmv1(b,p,x,y,m,n)
  281. char b[8][8],p;
  282. int x,y,m,n;
  283. {
  284.     int k;
  285.     k=0;
  286.     while ((x += m) >= 0 && x < 8 && (y += n) >= 0 && y<8)
  287.     {
  288.         if (b[x][y]==EMPTY) return 0;
  289.         if (b[x][y]== p ) return k;
  290.         if (x==0 || x==7 || y==0 || y==7)
  291.             k += 10;
  292.          else k++;
  293.     }
  294.     return 0;
  295. }
  296.  
  297.  
  298. notake(b,p,o,e,x,y)
  299. char b[8][8];
  300. char p,o,e;
  301. int x,y;
  302. {
  303.     return notak1(b,p,o,e,x,y,0,1)&&
  304.         notak1(b,p,o,e,x,y,1,1)&&
  305.         notak1(b,p,o,e,x,y,1,0)&&
  306.         notak1(b,p,o,e,x,y,1,-1);
  307. }
  308.  
  309.  
  310. notak1(b,p,o,e,x,y,m,n)
  311. char b[8][8],p,o,e;
  312. int x,y,m,n;
  313. {
  314.     int c1,c2;
  315.     c1 = notak2(b,p,o,e,x,y,m,n);
  316.     c2 = notak2(b,p,o,e,x,y,-m,-n);
  317.     return !(c1==o && c2==e || c1==e && c2==o);
  318. }
  319.  
  320.  
  321. notak2(b,p,o,e,x,y,m,n)
  322. char b[8][8],p,o,e;
  323. int x,y,m,n;
  324. {
  325.     x += m; y +=n;
  326.     if (x>=0 && x<=7 && y>=0 && y<=7)
  327.         while(b[x][y] == 0) {
  328.          x += m; y+=n;
  329.          if (x<0 || x>7 || y<0 || y>7 || b[x][y]==e)
  330.             return o;
  331.          }
  332.     while (x>=0 && x<=7 && y>=0 && y<=7 && b[x][y]==p)
  333.             { x +=m; y+=n; }
  334.     if (x<0 || x>7 || y<0 || y>7) return p;
  335.     return b[x][y];
  336. }
  337.  
  338.  
  339. putmov(b,p,x,y)
  340. char b[8][8];
  341. char p;
  342. int x,y;
  343. {
  344.     int i,j;
  345.     b[x][y] = p;
  346.     for (i= -1; i<=1; i++) for (j= -1; j<=1; j++) {
  347.         if ((i != 0 || j!=0)&&chkmv1(b,p,x,y,i,j)>0)
  348.             putmv1(b,p,x,y,i,j);
  349.      }
  350. }
  351.  
  352.  
  353. putmv1(b,p,x,y,m,n)
  354. char b[8][8];
  355. char p;
  356. int x,y,m,n;
  357. {
  358.     while ((x += m) >= 0 && x<8 && (y += n)>=0 && y<8) {
  359.         if (b[x][y] == EMPTY || b[x][y] == p) return;
  360.         b[x][y] = p;
  361.      }
  362. }
  363.  
  364.  
  365. struct mt {
  366.         int x;
  367.         int y;
  368.         int c;
  369.         int s;
  370.      };
  371.  
  372. my_mov(b,p,o,e,m,n)
  373. char b[8][8],p;
  374. int *m, *n;
  375. {
  376.     struct mt  t[64];
  377.     int i,k;
  378.     int cmpmov();
  379.     k = fillmt(b,p,o,e,t);
  380.     if (!k) return 0;
  381.     qsort (&t, k, 8, &cmpmov);
  382.     for (i=1; i<k; i++)
  383.         if (t[i].s != t[0].s || t[i].c != t[0].c)
  384.                         break;
  385.     k = rand() % i;
  386.     *m = t[k].x;
  387.     *n = t[k].y;
  388.     return 1;
  389. }
  390.  
  391. analyze(b,p,o,e)
  392. char b[8][8], p,o,e;
  393. {
  394.     struct mt  t[64];
  395.     char a[8][8];
  396.     int i,k,c;
  397.     k = fillmt(b,p,o,e,t);
  398.     cpybrd(a,b);
  399.     for (i=0; i<k; i++)
  400.       a[t[i].x][t[i].y] = ((c = 'F' - t[i].s) <= 'Z')?c:'Z';
  401.     prtbrd(a);
  402. }
  403.  
  404.  
  405. fillmt(b,p,o,e,t)
  406. char b[8][8],p,o,e;
  407. struct mt  t[64];
  408. {
  409.     int i,j,k;
  410.     k = 0;
  411.     for (i=0; i<8; i++) for(j=0; j<8; j++)
  412.        if (t[k].c = chkmov(b,p,i,j)) {
  413.             t[k].x =i;
  414.             t[k].y =j;
  415.             t[k].s = s_move(b,p,o,e,i,j);
  416.             ++k;
  417.         }
  418.     return k;
  419. }
  420.  
  421.  
  422.  
  423. s_move(b,p,o,e,i,j)
  424. char b[8][8], p, o, e;
  425. int i,j;
  426. {
  427.     char a[8][8];
  428.     int ok,s,k,l,side,oside;
  429.     int c,dkl;
  430.     cpybrd(a,b);
  431.     putmov(a,p,i,j);
  432.     side = 0;
  433.     if (i==0 || i==7) side++;
  434.     if (j==0 || j==7) side++;
  435.     s = 0;
  436.     ok = 0;
  437.     if (side==2 || notake(b,p,o,e,i,j)) ok++;
  438.     oside = 0;
  439.     for (k=0; k<8; k++) for(l=0; l<8; l++)
  440.      {
  441.         c=chkmov(a,o,k,l);
  442.         if (c==0) continue;
  443.         dkl = 1;
  444.         if (k==0 || k==7) { dkl+=2; oside|=4;}
  445.         if (l==0 || l==7) {dkl+=2; oside|=4; }
  446.         if (dkl==5) {dkl = 10; oside |= 16; }
  447.             else if (!notake(a,o,p,e,k,l))
  448.                     continue;
  449.         oside |= 1;
  450.         s -= dkl;
  451.         if (c>=10) { s -= 4; oside |= 8; }
  452.         }
  453.     if (s< -oside) s= -oside;
  454.     if (side>0) return s+side-7+10*ok;
  455.     if (i==1 || i==6) {s--; side++;}
  456.     if (j==1 || j==6) {s--; side++;}
  457.     if (side>0) return s;
  458.     if (i==2 || i==5) s++;
  459.     if (j==2 || j==5) s++;
  460.     return s;
  461. }
  462.  
  463. cmpmov(a,b)
  464. struct mt  *a, *b;
  465. {
  466.     if ((*a).s > (*b).s) return -1;
  467.     if ((*a).s < (*b).s) return 1;
  468.     if ((*a).c > (*b).c) return -1;
  469.     if ((*a).c < (*b).c) return 1;
  470.     return 0;
  471. }
  472.  
  473.  
  474.  
  475. clrbrd(b)
  476. char b[8][8];
  477. {
  478.     int i,j;
  479.     for (i=0; i<8; i++)
  480.         for (j=0; j<8; j++)
  481.             b[i][j]= EMPTY;
  482.     b[3][3] = b[4][4] = BLACK;
  483.     b[3][4] = b[4][3] = WHITE;
  484. }
  485.  
  486.  
  487. prtbrd(b)
  488. char b[8][8];
  489. {
  490.     int i,j;
  491.     printf("   1 2 3 4 5 6 7 8\n");
  492.     for (i=0; i<8; i++) {
  493.         printf("%2d",i+1);
  494.         for (j=0; j<8; j++) {
  495.             putchar(' ');
  496.             putchar(b[i][j]);
  497.          }
  498.         putchar('\n');
  499.      }
  500.     putchar('\n');
  501. }
  502.  
  503.  
  504. cpybrd(a,b)
  505. char *a, *b;
  506. {
  507.     int i;
  508.     i=64;
  509.     while (i--)
  510.         *a++ = *b++;
  511. }
  512.  
  513. cntbrd(b,p)
  514. char *b, p;
  515. {
  516.     int i,j;
  517.     i= 64; j=0;
  518.     while (i--)
  519.         if (*b++ == p) ++j;
  520.     return (j);
  521. }
  522.  
  523. printhelp()
  524. {
  525. FILE *fh;
  526. int lc;
  527. char str[82],c;
  528. printf("\nDo you want to see the instructions? (Y)");
  529. scanf("%s%",str);
  530. if(toupper(str[0])=='Y')
  531.  {
  532.   fh=open("othello.hlp",0);
  533.   lc=1;
  534.   while(fgets(str,80,fh))
  535.    {
  536.     if(lc++==22)
  537.      {
  538.       printf("\npress any key to continue...");
  539.       getchar();
  540.       printf("\n");
  541.       lc=1;
  542.      }
  543.    puts(str);
  544.  }
  545.  
  546.   close(fh);
  547.  }
  548. }
  549.